#include <iostream>

#include "apidemo.h"

JzAGVApi::JzAGVApi(std::string url)
{
    m_url = url;
    m_pHandle = curl_easy_init();
}

JzAGVApi::~JzAGVApi()
{
    if (m_pHandle != NULL)
    {
        curl_easy_cleanup(m_pHandle);
    }
}

std::string JzAGVApi::Get(const char *url)
{
    std::string body;
    if (url == NULL)
    {
        return body;
    }
    long response_code;

    curl_easy_setopt(m_pHandle, CURLOPT_HTTPGET, 1L);
    curl_easy_setopt(m_pHandle, CURLOPT_URL, url);
    curl_easy_setopt(m_pHandle, CURLOPT_WRITEFUNCTION, JzAGVApi::CurlWriteCallback);
    curl_easy_setopt(m_pHandle, CURLOPT_WRITEDATA, &body);
    curl_easy_setopt(m_pHandle, CURLOPT_TIMEOUT, 10L);

    /* Perform the request, res will get the return code */
    CURLcode res = curl_easy_perform(m_pHandle);
    /* Check for errors */
    if(res != CURLE_OK)
    {
        std::cout << "curl_easy_perform(): "
            << res << "-"
            << curl_easy_strerror(res);
        body = "";
        return body;
    }
    curl_easy_getinfo(m_pHandle, CURLINFO_RESPONSE_CODE, &response_code);
    if (response_code != 200)
    {
        std::cout << "status code: " << response_code << std::endl;
    }
    return body;
}

std::string JzAGVApi::Post(const char *url, const std::string &data)
{
    std::string body;
    long response_code;

    curl_easy_setopt(m_pHandle, CURLOPT_POST, 1L);
    curl_easy_setopt(m_pHandle, CURLOPT_URL, url);
    curl_easy_setopt(m_pHandle, CURLOPT_WRITEFUNCTION, JzAGVApi::CurlWriteCallback);
    curl_easy_setopt(m_pHandle, CURLOPT_WRITEDATA, &body);
    curl_easy_setopt(m_pHandle, CURLOPT_TIMEOUT, 10L);
    curl_easy_setopt(m_pHandle, CURLOPT_POSTFIELDS, data.c_str());

    /* Perform the request, res will get the return code */
    CURLcode res = curl_easy_perform(m_pHandle);
    /* Check for errors */
    if(res != CURLE_OK)
    {
        std::cout << "curl_easy_perform():"
            << res << "-"
            << curl_easy_strerror(res);
        body = "";
        return body;
    }
    curl_easy_getinfo(m_pHandle, CURLINFO_RESPONSE_CODE, &response_code);
    if (response_code != 200)
    {
        std::cout << "status code: " << response_code << std::endl;
    }
    return body;
}

size_t JzAGVApi::CurlWriteCallback(char* buffer, size_t size, size_t nitems, void* userdata)
{
    std::size_t length = size * nitems;
    if (userdata != NULL)
    {
        std::string* p = static_cast<std::string*>(userdata);
        p->append(buffer, length);
    }
    return length;
}


std::string JzAGVApi::GetRobot(int id)
{
    char uri[1024] = "";
    sprintf(uri, "%s/api/v1/robots/%d", m_url.c_str(), id);
    return this->Get(uri);
}

std::string JzAGVApi::GetRobots()
{
    char uri[1024] = "";
    sprintf(uri, "%s/api/v1/robots", m_url.c_str());

    return this->Get(uri);
}

std::string JzAGVApi::CreateMission()
{
    std::string m = "{\"ref_uuid\":\"uuid-1\", \"steps\":[{\"map_name\":\"Baiyun\", \"target\":9, \"action\":\"load\"}]}";

    char uri[1024] = "";
    sprintf(uri, "%s/api/v1/missions", m_url.c_str());

    return this->Post(uri, m);
}

std::string JzAGVApi::GetMission(int missionID)
{
    char uri[1024] = "";
    sprintf(uri, "%s/api/v1/missions/%d", m_url.c_str(), missionID);
    return this->Get(uri);
}

std::string JzAGVApi::GetMissionByUUID(std::string uuid)
{
    char uri[1024] = "";
    sprintf(uri, "%s/api/v1/uuid/missions/%s", m_url.c_str(), uuid.c_str());
    return this->Get(uri);
}

std::string JzAGVApi::CreateMissionCommand(int cmdType, int missionID, std::string missionUUID, bool sync)
{
    char uri[1024] = "";
    sprintf(uri, "%s/api/v1/mscmds", m_url.c_str());
    char data[1024] = "";
    // missionID or missionUUID, choose one
    if (missionID > 0)
    {
        sprintf(data, "{\"cmd\":%d, \"sync\": %s, \"mission_id\": %d}",
                cmdType,
                sync ? "true": "false",
                missionID);
    }
    else if (missionUUID != "")
    {
        sprintf(data, "{\"cmd\":%d, \"sync\": %s, \"mission_uuid\": %s}",
                cmdType,
                sync ? "true": "false",
                missionUUID.c_str());
    }
    else
    {
        std::cout << "mission_id or mission_uuid, choose one" << std::endl;
        return "";
    }

    return this->Post(uri, data);
}

std::string JzAGVApi::CheckMissionCommand(int cmdID)
{
    char uri[1024] = "";
    sprintf(uri, "%s/api/v1/mscmds/%d", m_url.c_str(), cmdID);
    return this->Get(uri);
}
